#ifndef IMAGEHANDLER
#define IMAGEHANDLER

#include <QFile>
#include <QImage>
#include <boost/thread.hpp>

class ImageHandler;
class ImageHandlerThread;

class ImageHandlerThread
{
private:
	ImageHandler* handler;
	int num_images;
	QImage* unprocessedImages;


public:
	ImageHandlerThread(ImageHandler* HANDLER);
	~ImageHandlerThread();

	void operator()();
};


class ImageHandler
{
private:
	QFile*  unloadedFiles;
	int     num_files;
	
	QImage* finalImage;
	QImage* tempImages;
	int num_images;
	


	/*
	 * Function pointers to callbacks
	 */
	void (*onCompletionMethod)(QImage*);
	void (*onErrorMethod)(void);
	
	boost::thread     * handlerThread;
	
public:

	QImage* loadAllImages(QFile* files, int numFiles);
	QImage* padImage(QImage* sourceImage, int padding);
	QImage* assembleImages(QImage* images, int num_images);
	void    asyncHandleImages();
	
	void setFinalImage(QImage* image);
	
	QFile* getFiles();
	int    getNumFiles();
	
	QImage* getTempImages();
	int    getNumImages();
	
	
	ImageHandler(QFile* files, int numFiles);
	~ImageHandler();
	
	void    asyncProcessAtlasTexture();
	
	void registerOnCompletionCallback(void(*callback)(QImage*));
	void registerOnErrorCallback(void(*callback)(void));

	void callOnCompletionMethod(QImage*);
	void callOnErrorCallback();
};

class TextureAllocator
{
private:
	int allocator_width, allocator_height;
	
	class AllocatorChunk
	{
	private:
		int chunk_width, chunk_height;
		QImage* image;
	public:
		AllocatorChunk(QImage* IMG, int width=256, int height=256);
	};
	
	int numMainChunks, numRemainderChunks;
	AllocatorChunk *mainChunks, *remainderChunks;
	
	QImage* finalImage;
	
	bool divideIntoChunks(int width, int height);
	
public:
	TextureAllocator(QImage* images, int width=1024, int height=1024);
	~TextureAllocator();
	
	QImage* getCopyOfFinalImage();
};

bool checkPowerOfTwo(unsigned long x)
{
    return (x != 0) && ((x & (x - 1)) == 0);
}


#endif